package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

const (
	PU_PREFIX     = "PU_"
	SENSOR_PREFIX = "Sensor_"
	BIDDER_PREFIX = "Bidder_"
)

//基站
type PU struct {
	Id   string `json:"id"`
	Idle bool   `json:"idle"`
}

//初始化数据
func initData(ctx contractapi.TransactionContextInterface) error {
	//初始化3个pu
	for i := 1; i <= 3; i++ {
		id := "00" + strconv.Itoa(i)
		pu := PU{
			Id:   "PU_" + id,
			Idle: true,
		}
		jsonByte, err := json.Marshal(pu)
		if err != nil {
			return err
		}
		key, err := ctx.GetStub().CreateCompositeKey(PU_PREFIX, []string{pu.Id})
		if err != nil {
			return err
		}
		err = ctx.GetStub().PutState(key, jsonByte)
		if err != nil {
			return err
		}
		fmt.Printf("insert PU success,key:%v,value:%v", key, pu)
	}
	//初始化5个Sensor
	for i := 1; i <= 5; i++ {
		id := "00" + strconv.Itoa(i)
		sensor := Sensor{
			Address:    "Sensor_" + id,
			Deposit:    100.0,
			TrustValue: 0.9 + float64(i)/100.0,
		}
		jsonByte, err := json.Marshal(sensor)
		if err != nil {
			return err
		}
		key, err := ctx.GetStub().CreateCompositeKey(SENSOR_PREFIX, []string{sensor.Address})
		if err != nil {
			return err
		}
		err = ctx.GetStub().PutState(key, jsonByte)
		if err != nil {
			return err
		}
		fmt.Printf("insert sensor success,key:%v,value:%v", key, sensor)
	}
	//初始化3个bidder
	for i := 1; i <= 3; i++ {
		id := "00" + strconv.Itoa(i)
		bidder := Bidder{
			BidderId: "Bidder_" + id,
			Deposit:  1000.0,
		}
		jsonByte, err := json.Marshal(bidder)
		if err != nil {
			return err
		}
		key, err := ctx.GetStub().CreateCompositeKey(BIDDER_PREFIX, []string{bidder.BidderId})
		if err != nil {
			return err
		}
		err = ctx.GetStub().PutState(key, jsonByte)
		if err != nil {
			return err
		}
		fmt.Printf("insert bidder success,key:%v,value:%v", key, bidder)
	}
	return nil
}

//删除初始化数据
func DeleteInitData(ctx contractapi.TransactionContextInterface) error {
	resultsIter, err := ctx.GetStub().GetStateByPartialCompositeKey(PU_PREFIX, []string{})
	if err != nil {
		return err
	}
	defer resultsIter.Close()

	for resultsIter.HasNext() {
		queryResponse, _ := resultsIter.Next()
		err = ctx.GetStub().DelState(queryResponse.Key)
		if err != nil {
			return err
		}
	}

	resultsIter, err = ctx.GetStub().GetStateByPartialCompositeKey(SENSOR_PREFIX, []string{})
	if err != nil {
		return err
	}
	defer resultsIter.Close()

	for resultsIter.HasNext() {
		queryResponse, _ := resultsIter.Next()
		err = ctx.GetStub().DelState(queryResponse.Key)
		if err != nil {
			return err
		}
	}

	resultsIter, err = ctx.GetStub().GetStateByPartialCompositeKey(BIDDER_PREFIX, []string{})
	if err != nil {
		return err
	}
	defer resultsIter.Close()

	for resultsIter.HasNext() {
		queryResponse, _ := resultsIter.Next()
		err = ctx.GetStub().DelState(queryResponse.Key)
		if err != nil {
			return err
		}
	}
	return nil
}

//查询pu
func (t *SimpleChaincode) QueryPUList(ctx contractapi.TransactionContextInterface) ([]*PU, error) {
	resultsIter, err := ctx.GetStub().GetStateByPartialCompositeKey(PU_PREFIX, []string{})
	if err != nil {
		return nil, fmt.Errorf("QueryPuList: %v", err)
	}
	defer resultsIter.Close()

	var puList []*PU
	for resultsIter.HasNext() {
		queryResponse, err := resultsIter.Next()
		if err != nil {
			return nil, fmt.Errorf("QueryPuList: %v", err)
		}
		var pu PU
		err = json.Unmarshal(queryResponse.Value, &pu)
		if err != nil {
			return nil, fmt.Errorf("QueryPuList: %v", err)
		}
		puList = append(puList, &pu)
	}

	return puList, nil
}

//查询Sensor
func (t *SimpleChaincode) QuerySensorList(ctx contractapi.TransactionContextInterface) ([]*Sensor, error) {
	resultsIter, err := ctx.GetStub().GetStateByPartialCompositeKey(SENSOR_PREFIX, []string{})
	if err != nil {
		return nil, fmt.Errorf("QuerySensorList: %v", err)
	}
	defer resultsIter.Close()

	var sensorList []*Sensor
	for resultsIter.HasNext() {
		queryResponse, err := resultsIter.Next()
		if err != nil {
			return nil, fmt.Errorf("QuerySensorList: %v", err)
		}
		var sensor Sensor
		err = json.Unmarshal(queryResponse.Value, &sensor)
		if err != nil {
			return nil, fmt.Errorf("QuerySensorList: %v", err)
		}
		sensorList = append(sensorList, &sensor)
	}

	return sensorList, nil
}

//查询bidder
func (t *SimpleChaincode) QueryBidderList(ctx contractapi.TransactionContextInterface) ([]*Bidder, error) {
	resultsIter, err := ctx.GetStub().GetStateByPartialCompositeKey(BIDDER_PREFIX, []string{})
	if err != nil {
		return nil, fmt.Errorf("QueryBidderList: %v", err)
	}
	defer resultsIter.Close()

	var bidderList []*Bidder
	for resultsIter.HasNext() {
		queryResponse, err := resultsIter.Next()
		if err != nil {
			return nil, fmt.Errorf("QueryBidderList: %v", err)
		}
		var bidder Bidder
		err = json.Unmarshal(queryResponse.Value, &bidder)
		if err != nil {
			return nil, fmt.Errorf("QueryBidderList: %v", err)
		}
		bidderList = append(bidderList, &bidder)
	}

	return bidderList, nil
}

//根据sacId从区块链查询sac
func (t *SimpleChaincode) GetSACById(ctx contractapi.TransactionContextInterface, sacId string) (*SAC, error) {
	b, err := ctx.GetStub().GetState(sacId)
	if b == nil {
		return nil, fmt.Errorf("key doesn't exist")
	}
	if err != nil {
		return nil, err
	}
	var sac SAC
	err = json.Unmarshal(b, &sac)
	if err != nil {
		return nil, err
	}
	return &sac, nil
}

//根据cscId从区块链查询csc
func (t *SimpleChaincode) GetCSCById(ctx contractapi.TransactionContextInterface, sacId string) (*CSC, error) {
	b, err := ctx.GetStub().GetState(sacId)
	if b == nil {
		return nil, fmt.Errorf("key doesn't exist")
	}
	if err != nil {
		return nil, err
	}
	var csc CSC
	err = json.Unmarshal(b, &csc)
	if err != nil {
		return nil, err
	}
	return &csc, nil
}

//根据bidderId从区块链查询bidder
func (t *SimpleChaincode) GetBidderById(ctx contractapi.TransactionContextInterface, bidderId string) (*Bidder, error) {
	key, err := ctx.GetStub().CreateCompositeKey(BIDDER_PREFIX, []string{bidderId})
	if err != nil {
		return nil, err
	}

	b, err := ctx.GetStub().GetState(key)
	if b == nil {
		return nil, fmt.Errorf("key doesn't exist")
	}
	if err != nil {
		return nil, err
	}
	var bidder Bidder
	err = json.Unmarshal(b, &bidder)
	if err != nil {
		return nil, err
	}
	return &bidder, nil
}

//根据Id从区块链查询PU
func (t *SimpleChaincode) GetPUById(ctx contractapi.TransactionContextInterface, PUId string) (*PU, error) {
	key, err := ctx.GetStub().CreateCompositeKey(PU_PREFIX, []string{PUId})
	if err != nil {
		return nil, err
	}

	b, err := ctx.GetStub().GetState(key)
	if b == nil {
		return nil, fmt.Errorf("key doesn't exist")
	}
	if err != nil {
		return nil, err
	}
	var pu PU
	err = json.Unmarshal(b, &pu)
	if err != nil {
		return nil, err
	}
	return &pu, nil
}

//生成uuid
func UUID256() string {
	i := time.Now().UnixNano()
	s := strconv.FormatInt(i, 10)
	return Sha256(s)
}

//Sha256加密
func Sha256(src string) string {
	m := sha256.New()
	m.Write([]byte(src))
	res := hex.EncodeToString(m.Sum(nil))
	return res
}
